package com.lightboat.web.controller.crm;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lightboat.common.annotation.Log;
import com.lightboat.common.constant.RedisConstants;
import com.lightboat.common.core.controller.BaseController;
import com.lightboat.common.core.domain.AjaxResult;
import com.lightboat.common.core.domain.bo.LogisticsOrderBo;
import com.lightboat.common.core.page.TableDataInfo;
import com.lightboat.common.core.text.Convert;
import com.lightboat.common.enums.BusinessType;
import com.lightboat.common.enums.OperationTypeEnum;
import com.lightboat.common.enums.OrderType;
import com.lightboat.common.enums.RoleEnum;
import com.lightboat.common.exception.ServiceException;
import com.lightboat.common.utils.ChainOrderBy;
import com.lightboat.common.utils.PageUtils;
import com.lightboat.common.utils.RedisUtils;
import com.lightboat.common.utils.StringUtils;
import com.lightboat.system.domain.CrmOrder;
import com.lightboat.system.domain.CrmProductStockRecord;
import com.lightboat.system.domain.request.*;
import com.lightboat.system.service.ICrmOrderService;
import com.lightboat.system.service.ICrmProductService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 订单Controller
 *
 * @author lightboat
 * @date 2025-08-14
 */
@Tag(name = "订单管理")
@RestController
@RequiredArgsConstructor
@RequestMapping("/system/order")
public class CrmOrderController extends BaseController {

    private final ICrmOrderService crmOrderService;
    private final ICrmProductService crmProductService;

    /**
     * 查询订单列表
     */
    @Operation(summary = "查询订单列表")
    @PreAuthorize("@ss.hasPermis('platformOrders:orders:list','platformOrders:rpOrders:list','platformOrders:repurchaseOrderStatistics:list','customerService:order:list','customerService:repeatPurchaseOrder:list','customerService:order:list')")
    @GetMapping("/list")
    public TableDataInfo<CrmOrder> list(CrmOrderQueryRequest request) {
        List<String> roleKeys = getLoginUser().getUser().getRoleKeys();
        ChainOrderBy<CrmOrder> chainOrderBy = PageUtils.<CrmOrder>chainOrderBy();
        if (ObjUtil.isNotEmpty(request.getTypeCode())){
            if ("1".equals(request.getTypeCode())){
                chainOrderBy
                        .orderByAsc("c_top_status")
                        .orderByDesc(ObjUtil.isNotEmpty(request.getTopStatus()), "c_top_time");
            }else if ("2".equals(request.getTypeCode())){
                chainOrderBy
                        .orderByAsc("top_status")
                        .orderByDesc(ObjUtil.isNotEmpty(request.getTopStatus()), "top_time");
            }
        }else{
            chainOrderBy
                    .orderByAsc("top_status")
                    .orderByAsc("c_top_status")
                    .orderByDesc(ObjUtil.isNotEmpty(request.getTopStatus()), "top_time")
                    .orderByDesc(ObjUtil.isNotEmpty(request.getTopStatus()), "c_top_time");
        }
        chainOrderBy
                .orderByDesc(ObjUtil.isNotEmpty(Opt.ofNullable(request.getParams()).map(m->m.get("orderSignTime")).orElse(null)) && Convert.toInt(request.getParams().get("orderSignTime")) == 1, "logistics_sign_time")
                .orderByAsc(ObjUtil.isNotEmpty(Opt.ofNullable(request.getParams()).map(m->m.get("orderSignTime")).orElse(null)) && Convert.toInt(request.getParams().get("orderSignTime")) == 0, "logistics_sign_time")
                .orderBy(CrmOrder::getOrderTime, false).orderByDesc(CrmOrder::getCreateTime).apply();
        startPage();
        CrmOrder crmOrder = BeanUtil.copyProperties(request, CrmOrder.class);
        crmOrder.setIsChildren(0);
        crmOrder.setParams(request.getParams());
        if (roleKeys.contains(RoleEnum.SALE_USER.getRoleCode())) {
            crmOrder.setSalesmanId(getUserId());
        }
        if (ObjUtil.isNotEmpty(request.getTopType())) {
            List<String> topTypes = StrUtil.splitTrim(request.getTopType(), ",");
            crmOrder.getParams().put("topTypes", topTypes);
            crmOrder.setTopType(null);
        }
        if (ObjUtil.isNotEmpty(request.getCTopType())) {
            List<String> topTypes = StrUtil.splitTrim(request.getCTopType(), ",");
            crmOrder.getParams().put("cTopTypes", topTypes);
            crmOrder.setCTopType(null);
        }
        if (ObjUtil.isNotEmpty(request.getOrderStatus())) {
            List<String> orderStatuses = StrUtil.splitTrim(request.getOrderStatus(), ",");
            crmOrder.getParams().put("orderStatus", orderStatuses);
            crmOrder.setOrderStatus(null);
        }
        List<CrmOrder> list = crmOrderService.selectCrmOrderList(crmOrder);
        clearPage();
        crmOrderService.combineOrderData(list, crmOrder);
        return getDataTable(list);
    }




    /**
     * 查询客户订单统计
     */
    @Operation(summary = "查询客户订单统计")
    @PreAuthorize("@ss.hasPermi('system:order:list')")
    @GetMapping("customer/list/statistics")
    public AjaxResult customerStatistics(CustomerOrderQueryRequest request) {

        Map<String, Object> serviceMap = crmOrderService.getMap(
                Wrappers.<CrmOrder>query()
                        .select("customer_id as customerId", "sum(COALESCE(total_amount,0)) as totalAmount", "count(1) count")
                        .eq("customer_id", request.getCustomerId())
                        .eq(ObjUtil.isNotEmpty(request.getOrderType()), "order_type", request.getOrderType())
                        .eq("is_children", 0).groupBy("customer_id")
        );
        return AjaxResult.success(serviceMap);
    }

    /**
     * 查询客户订单列表
     */
    @Operation(summary = "查询客户订单列表")
    @PreAuthorize("@ss.hasPermi('system:order:list')")
    @GetMapping("customer/list")
    public TableDataInfo<CrmOrder> customerAllList(CustomerOrderQueryRequest request) {
        PageUtils.<CrmOrder>chainOrderBy().orderByAsc(CrmOrder::getTopStatus).orderByDesc(CrmOrder::getTopTime).orderBy(CrmOrder::getOrderTime, false).orderByDesc(CrmOrder::getCreateTime).apply();
        startPage();
        CrmOrder crmOrder = BeanUtil.copyProperties(request, CrmOrder.class);
        crmOrder.setIsChildren(0);
        Wrapper<CrmOrder> queryWrapper = Wrappers.<CrmOrder>lambdaQuery()
                .eq(CrmOrder::getCustomerId, crmOrder.getCustomerId())
                .eq(CrmOrder::getIsChildren, crmOrder.getIsChildren())
                .eq(ObjUtil.isNotEmpty(request.getOrderType()), CrmOrder::getOrderType, request.getOrderType())
                .and(StringUtils.isNoneBlank(crmOrder.getSearchValue()), a -> {
                    a.like(CrmOrder::getOrderNo, crmOrder.getSearchValue()).or()
                            .like(CrmOrder::getReceiverPhone, crmOrder.getSearchValue()).or()
                            .like(CrmOrder::getReceiverAddress, crmOrder.getSearchValue()).or()
                            .like(CrmOrder::getReceiverName, crmOrder.getSearchValue()).or()
                            .like(CrmOrder::getSalesmanName, crmOrder.getSearchValue());
                });
        List<CrmOrder> list = crmOrderService.list(queryWrapper);
        clearPage();
        crmOrderService.combineOrderData(list, crmOrder);
        return getDataTable(list);
    }

    /**
     * 查询待分配订单列表
     */
    @Operation(summary = "查询待分配订单列表")
    @PreAuthorize("@ss.hasPermi('customerService:pendingOrders:list')")
    @GetMapping("/not/assigned/list")
    public TableDataInfo<CrmOrder> notAssignedList(CrmOrderQueryRequest request) {
        PageUtils.<CrmOrder>chainOrderBy().orderBy(CrmOrder::getOrderTime, false).apply();
        startPage();
        CrmOrder crmOrder = BeanUtil.copyProperties(request, CrmOrder.class);
        if (ObjUtil.isNotEmpty(request.getTopType())) {
            List<String> topTypes = StrUtil.splitTrim(request.getTopType(), ",");
            crmOrder.getParams().put("topTypes", topTypes);
            crmOrder.setTopType(null);
        }
        if (ObjUtil.isNotEmpty(request.getOrderStatus())) {
            List<String> orderStatuses = StrUtil.splitTrim(request.getOrderStatus(), ",");
            crmOrder.getParams().put("orderStatus", orderStatuses);
            crmOrder.setOrderStatus(null);
        }
        List<CrmOrder> list = crmOrderService.selectCrmOrderList(crmOrder, Wrappers.<CrmOrder>query().isNull("crm_order.salesman_id"));
        clearPage();
        crmOrderService.combineOrderData(list, crmOrder);
        return getDataTable(list);
    }

    /**
     * 查询公海订单列表
     */
    @Operation(summary = "查询公海订单列表")
    @PreAuthorize("@ss.hasPermi('platformOrders:highSeasOrder:list')")
    @GetMapping("/highSeas/list")
    public TableDataInfo<CrmOrder> highSeasList(CrmOrderQueryRequest request) {
        PageUtils.<CrmOrder>chainOrderBy().orderBy(CrmOrder::getOrderTime, false).apply();
        startPage();
        CrmOrder crmOrder = BeanUtil.copyProperties(request, CrmOrder.class);
        if (ObjUtil.isNotEmpty(request.getTopType())) {
            List<String> topTypes = StrUtil.splitTrim(request.getTopType(), ",");
            crmOrder.getParams().put("topTypes", topTypes);
            crmOrder.setTopType(null);
        }
        if (ObjUtil.isNotEmpty(request.getOrderStatus())) {
            List<String> orderStatuses = StrUtil.splitTrim(request.getOrderStatus(), ",");
            crmOrder.getParams().put("orderStatus", orderStatuses);
            crmOrder.setOrderStatus(null);
        }
        List<CrmOrder> list = crmOrderService.selectHighSeasOrderList(crmOrder);
        clearPage();
        crmOrderService.combineOrderData(list, crmOrder);
        return getDataTable(list);
    }

    /**
     * 获取订单详细信息
     */
    @Operation(summary = "获取订单详细信息")
    // @PreAuthorize("@ss.hasPermi('system:order:query')")
    @GetMapping(value = "/{orderId}")
    public AjaxResult getInfo(@PathVariable("orderId") Long orderId) {
        return success(crmOrderService.selectCrmOrderByOrderId(orderId));
    }

    /**
     * 新增复购订单
     */
    @Operation(summary = "新增复购订单")
    @PreAuthorize("@ss.hasPermi('system:order:add:repurchase')")
    @Log(title = "订单", businessType = BusinessType.INSERT)
    @PostMapping("repurchase/add")
    public AjaxResult addRepurchase(@RequestBody @Validated AddRepurchaseOrderRequest request) {
        return toAjax(crmOrderService.addRepurchase(request));
    }

    /**
     * 新增多包裹复购订单
     * @param request
     * @return
     */
    @Operation(summary = "新增多包裹复购订单")
    @PreAuthorize("@ss.hasPermi('system:order:add:repurchases')")
    @Log(title = "订单", businessType = BusinessType.INSERT)
    @PostMapping("repurchase/adds")
    public AjaxResult addRepurchases(@RequestBody @Validated AddsRepurchaseOrderRequest request) {
        return toAjax(crmOrderService.addRepurchases(request));
    }

    /**
     * 新增复购补货订单
     * @param request
     * @return
     */
    @Operation(summary = "新增复购补货订单")
    @PreAuthorize("@ss.hasPermi('system:order:add:replenishment')")
    @Log(title = "订单", businessType = BusinessType.INSERT)
    @PostMapping("replenishment/add")
    public AjaxResult addReplenishment(@RequestBody @Validated AddReplenishmentOrderRequest request) {
        return toAjax(crmOrderService.addReplenishment(request));
    }

    /**
     * 追加复购订单
     * @param request
     * @return
     */
    @Operation(summary = "追加复购订单")
    @PreAuthorize("@ss.hasPermi('system:order:add:appendRepurchase')")
    @Log(title = "订单", businessType = BusinessType.INSERT)
    @PostMapping("appendRepurchase/add")
    public AjaxResult appendRepurchase(@RequestBody @Validated AppendRepurchaseOrderRequest request) {
        return toAjax(crmOrderService.appendRepurchase(request));
    }

    /**
     * 修改订单
     */
    @Operation(summary = "修改订单")
    @PreAuthorize("@ss.hasPermi('system:order:edit')")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody CrmOrder crmOrder) {
        return toAjax(crmOrderService.updateCrmOrder(crmOrder));
    }

    /**
     * 删除订单
     */
    @Operation(summary = "删除订单")
    @PreAuthorize("@ss.hasPermi('system:order:remove')")
    @Log(title = "订单", businessType = BusinessType.DELETE)
    @DeleteMapping("/{orderIds}")
    public AjaxResult remove(@PathVariable Long[] orderIds) {
        return toAjax(crmOrderService.deleteCrmOrderByOrderIds(orderIds));
    }

    /**
     * 订单置顶
     */
    @Operation(summary = "订单置顶")
    @PreAuthorize("@ss.hasPermi('system:order:top')")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PostMapping("/top")
    public AjaxResult orderTop(@RequestBody @Validated OrderTopRequest request) {
        return toAjax(crmOrderService.orderTop(request));
    }


    /**
     * 分配业务员
     * @param request
     * @return
     */
    @Operation(summary = "分配业务员")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('system:order:assign')")
    @PostMapping("/assign/salesman")
    public AjaxResult assignSalesman(@RequestBody AssignSalesmanRequest request) {
        String message = crmOrderService.assignSalesman(request);
        return success(message);
    }


    /**
     * 订单物流发货
     * @param request
     * @return
     */
    @Operation(summary = "订单发货")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('system:order:shipping')")
    @PostMapping("/logistics/shipping")
    public AjaxResult logisticsShipping(@RequestBody @Validated LogisticsShippingRequest request) {
        LogisticsOrderBo logisticsOrderBo = crmOrderService.logisticsShipping(request);
        return success(logisticsOrderBo);
    }

    /**
     * 订单物流拦截
     * @param request
     * @return
     */
    @Operation(summary = "订单物流拦截")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('system:order:logistics:cancel')")
    @RequestMapping(path = "/logistics/cancel",method = {RequestMethod.PUT,RequestMethod.POST})
    public AjaxResult logisticsCancel(@RequestBody @Validated LogisticsCancelRequest request) {
        LogisticsOrderBo logisticsOrderBo = crmOrderService.logisticsCancel(request);
        return success(logisticsOrderBo);
    }

    /**
     * 订单取消
     * @param request
     * @return
     */
    @Operation(summary = "订单取消")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('system:order:cancel')")
    @PostMapping("/cancel")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult orderCancel(@RequestBody LogisticsShippingRequest request) {
        Boolean aBoolean = RedisUtils.builder().redissonLock(RedisConstants.ORDER_PREFIX + request.getOrderId(), () -> {
            CrmOrder crmOrder = crmOrderService.getById(request.getOrderId());
            if (crmOrder == null) {
                throw new ServiceException("订单不存在");
            }
            if (crmOrder.getOrderStatus() != 140) {
                throw new ServiceException("订单状态异常");
            }

            if (crmOrder.getIsMultiPackage() == 1) {
                LambdaUpdateWrapper<CrmOrder> wrapper = Wrappers.<CrmOrder>lambdaUpdate()
                        .set(CrmOrder::getVerRemark, request.getRemark())
                        .set(CrmOrder::getOrderStatus, 130)
                        .set(CrmOrder::getLogisticsNo,null)
                        .eq(CrmOrder::getRelatedOrderId, crmOrder.getOrderId())
                        .eq(CrmOrder::getIsChildren, 1)
                        .eq(CrmOrder::getOrderType, OrderType.REPURCHASE.getType());
                boolean update = crmOrderService.update(wrapper);
                if (update && Objects.equals(crmOrder.getOrderType(), OrderType.REPURCHASE.getType())) {
                    crmOrderService.list(Wrappers.<CrmOrder>lambdaQuery().select(CrmOrder::getProductCollection)).forEach(item->{
                        item.getProductCollection().forEach(mm->{
                            CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                            crmProductStockRecord.setProductId(mm.getProductId());
                            crmProductStockRecord.setOrderId(item.getOrderId());
                            crmProductStockRecord.setOrderStatus(3);
                            crmProductStockRecord.setChangeQuantity(Convert.toLong(mm.getNum()));
                            crmProductService.stockOperation(crmProductStockRecord, OperationTypeEnum.ADD);
                        });
                    });
                }
            }else {
                if (Objects.equals(crmOrder.getOrderType(), OrderType.REPURCHASE.getType())) {
                    crmOrder.getProductCollection().forEach(mm->{
                        CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                        crmProductStockRecord.setProductId(mm.getProductId());
                        crmProductStockRecord.setOrderId(crmOrder.getOrderId());
                        crmProductStockRecord.setOrderStatus(3);
                        crmProductStockRecord.setChangeQuantity(Convert.toLong(mm.getNum()));
                        crmProductService.stockOperation(crmProductStockRecord, OperationTypeEnum.ADD);
                    });
                }
            }

            CrmOrder updateOrder = new CrmOrder();
            updateOrder.setOrderId(request.getOrderId());
            updateOrder.setOrderStatus(130);
            return crmOrderService.updateById(updateOrder);
        }, StringUtils.format("订单：{},取消已在处理中...", request.getOrderId()));

        return toAjax(aBoolean);
    }


    /**
     * 订单核销
     */
    @Operation(summary = "订单核销")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('system:order:verification')")
    @PostMapping("/verification")
    public AjaxResult verification(@RequestBody @Validated VerificationOrderRequest request) {
        return toAjax(crmOrderService.verification(request));
    }

    /**
     * 订单完成
     */
    @Operation(summary = "订单完成")
    @Log(title = "订单", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('system:order:complete')")
    @PostMapping("/complete")
    public AjaxResult completeOrder(@RequestBody @Validated CompleteOrderRequest request) {
        return toAjax(crmOrderService.completeOrder(request));
    }
}